package com.netty.pro.netty.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author xuzn
 * @ClassName: NioServer
 * @ProjectName echo-project
 * @date 2020/3/6/21:11
 */
public class NioServer {
  public static void main(String[] args) throws Exception {
    // 创建ServerSocketChannel
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    // 得到一个selector对象
    Selector selector = Selector.open();
    // 绑定端口,在服务器段监听
    serverSocketChannel.socket().bind(new InetSocketAddress(7000));
    // 设置为非阻塞
    serverSocketChannel.configureBlocking(false);
    // 将channel注册到selector,监听的事件为accetp
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    // 循环等待客户端链接
    while (true) {
      if (selector.select(1000) == 0) {
        System.out.println("等待了一秒,服务器无连接~~");
        continue;
      }
      // 这里得到了有事件发生的selectionKey的集合
      Set<SelectionKey> selectionKeys = selector.selectedKeys();
      // 通过selectionKey反向获取channel
      Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
      while (selectionKeyIterator.hasNext()) {
        SelectionKey key = selectionKeyIterator.next();
        // 判断这个key的监听事件是不是accept
        if (key.isAcceptable()) {
          // 给客户端生成一个socketchannel
          SocketChannel socketChannel = serverSocketChannel.accept();
          socketChannel.configureBlocking(false);
          System.out.println("客户端链接成功,生成一个socketChannel:" + socketChannel.hashCode());
          // 同样将socketChannel注册到selector上去
          socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
        }

        if (key.isReadable()) {
          // 通过key反向获取channel
          SocketChannel channel = (SocketChannel) key.channel();
          // 获取到这个channel关联的buffer
          ByteBuffer buffer = (ByteBuffer) key.attachment();
          channel.read(buffer);
          System.out.println("从客户端发过来的内容是" + new String(buffer.array()));
        }
        // 手动删掉key
        selectionKeyIterator.remove();
      }
    }
  }
}
